﻿using System.Collections.Generic;
using Library.OrmEnterpriseEntity.TableInfo;
using System.Text;


namespace Library.OrmEnterpriseEntity {
	/// <summary>
	/// 
	/// </summary>
	public class QueryStatement : QueryBuilder {
		private readonly List<KeyValuePair<DbTableView, string>> _selectTables;

		internal GlobalEntityView RootRowType { get; private set; }

		internal List<DbColumnView> SelectCols { get; private set; }

		internal GlobalEntity.EntityCreator Creator;
		internal List<QueryParameter> Parameters { get; private set; }
		internal QueryStatement(GlobalEntityView root) {
			SelectCols = new List<DbColumnView>();
			Root = root;
			Parameters = new List<QueryParameter>();
			Joints = new JoinCollection(this);
			Orders = new List<OrderStatement>();
			_selectTables = new List<KeyValuePair<DbTableView, string>>();
			if (Root.ColumnRowType != null) RootRowType = Root;
		}

		internal string TableAlias(DbTableView table) {
			foreach (var t in _selectTables) {
				if (ReferenceEquals(t.Key, table)) return t.Value;
			}
			var kv = new KeyValuePair<DbTableView, string>(table, "t" + _selectTables.Count);
			_selectTables.Add(kv);
			return kv.Value;
		}

		protected internal DbColumnView CountCol;
		protected internal DbColumnView[] Groups;
		protected internal DbColumnView[] Sums;
		protected internal readonly IList<JoinStatement> Joints;
		protected internal GlobalEntityView Root { get; private set; }
		protected QueryExpBuilder WhereExpression;
		protected internal readonly List<OrderStatement> Orders;
		internal QueryExpBuilder GetWhereAtBuild() {
			if (WhereExpression == null) {
				if (CrossAll) WhereExpression = new QueryExpBuilder(this);
				else {
					if (Crosses != null && Crosses.Count > 0) {
						if (RootRowType != null && RootRowType.ColumnRowType != null)
							WhereExpression = new QueryExpBuilder(RootRowType.ColumnRowType, QueryOperator.In, Crosses);

					} else {
						if (RootRowType != null) {
							var ep = RootRowType.InnerExpression(this);
							if (ep == null) ep = new QueryExpBuilder(this);
							WhereExpression = ep;
						}
					}
				}
			} else {
				if (!CrossAll) {
					if (Crosses != null && Crosses.Count > 0) {
						if (RootRowType != null && RootRowType.ColumnRowType != null)
							WhereExpression = WhereExpression.Add(new QueryExpBuilder(RootRowType.ColumnRowType, QueryOperator.In, Crosses), ExpressionOperator.And);
					} else if (RootRowType != null) {
						var ep = RootRowType.InnerExpression(this);
						if (ep != null) {
							WhereExpression = WhereExpression.Add(ep, ExpressionOperator.And);
						}
					}
				}


				return WhereExpression;
			}
			if (WhereExpression == null) WhereExpression = new QueryExpBuilder(this);
			else {
				if (WhereExpression.Statement == null) WhereExpression.Statement = this;
			}

			return WhereExpression;

		}
		/// <summary>
		/// Excute the query statement
		/// </summary>
		/// <returns></returns>
		public virtual int Excute() {
			return 0;
		}
		/// <summary> 
		/// Get or set cross all row for current statement
		/// </summary>
		public bool CrossAll { get; set; }

		internal List<short> Crosses;
		/// <summary>
		/// Get the list of cross row for current statement
		/// </summary>
		public List<short> CrossList {
			get { return Crosses ?? (Crosses = new List<short>()); }
		}

		private class JoinCollection : Util.ListBase<JoinStatement> {
			private readonly QueryStatement _queryStatement;
			public JoinCollection(QueryStatement queryStatement) {
				_queryStatement = queryStatement;
			}
			public override void Insert(int index, JoinStatement item) {
				base.Insert(index, item);
				if (_queryStatement.RootRowType == null) {
					if (item.JoinTable.ColumnRowType != null) _queryStatement.RootRowType = item.JoinTable;
				}
			}
			public override void Add(JoinStatement item) {
				base.Add(item);
				if (_queryStatement.RootRowType == null) {
					if (item.JoinTable.ColumnRowType != null) _queryStatement.RootRowType = item.JoinTable;
				}
			}
		}

		protected internal StringBuilder SqlTracking {
			get;
			protected set;
		}
	}
}
